package ctf.evaluation.SimulatorTests;

import java.io.IOException;

import model.Player.PlayerState;

import ctf.evaluation.Point;
import ctf.evaluation.TestCase;
import ctf.evaluation.simulator.ConnectionManager;
import ctf.evaluation.simulator.data.Player;
import ctf.evaluation.simulator.data.State;
import ctf.evaluation.simulator.play.TCTF;
import ctf.evaluation.simulator.responses.CommandResponse;
import ctf.evaluation.simulator.responses.GameOverException;
import ctf.evaluation.simulator.responses.RoundOverException;
import ctf.evaluation.simulator.responses.StateResponse;
import ctf.model.Side;
import ctf.network.NetworkException;
import ctf.network.ProtocolError;
import ctf.network.SocketClosedException;
import ctf.network.UninitializedSocketException;
import ctf.network.tcp.Connection;

public class TCTFTests extends TestCase {
	private ConnectionManager connections = ConnectionManager.instance();
	private Connection red, blue;

	public void setUp() throws Exception {
		ConnectionManager connections = ConnectionManager.instance();
		connections.enterState(ConnectionManager.STEALState.PLAY);

		red = connections.red();
		blue = connections.blue();
	}
	public void testTCTFIncreasedByOpponentRunningOut() throws IOException, NetworkException, ProtocolError, RoundOverException, GameOverException{
		Point playerPosition = new Point(40,125);
		Point player2Position = new Point(95,125);
		
		
		blue.sendLine("placePlayer 0 " + player2Position.toSTEAL());
		new CommandResponse(blue);

		red.sendLine("placePlayer 0 " + playerPosition.toSTEAL());
		new CommandResponse(red);
		
		red.sendLine("accelerate 0 0 2");
		new CommandResponse(red);

		while(true){			
			sleep(100);
			red.sendLine("getState");
			State state = (new StateResponse(red)).state();
			Player player = state.team(Side.LEFT).player(0);
			if (player.location().x > 80){
				assertEquals(Player.State.DEFENDING, state.team(Side.LEFT).player(0).state());
				break;
			}
		}
		player2Position = new Point(150,125);
		blue.sendLine("placePlayer 0 " + player2Position.toSTEAL());
		new CommandResponse(blue);
		red.sendLine("accelerate 0 0 -2");
		new CommandResponse(red);
		
		while(true){			
			sleep(20);
			red.sendLine("getState");
			State state = (new StateResponse(red)).state();
			Player player = state.team(Side.LEFT).player(0);
			if (player.speed() > -0.05 && player.speed() < 0.05) {
				break;
			}
		}

		
		red.sendLine("getState");
		State state = (new StateResponse(red)).state();

		assertEquals(Player.State.TCTF, state.team(Side.LEFT).player(0).state());
		
	}

	public void testEnterTCTF() throws IOException, NetworkException, ProtocolError, RoundOverException, GameOverException{
		Point playerPosition = new Point(60,125);

		red.sendLine("placePlayer 0 " + playerPosition.toSTEAL());

		new CommandResponse(red);
		red.sendLine("accelerate 0 0 2");
		new CommandResponse(red);
		sleep(1000);
		red.sendLine("getState");
		State state = (new StateResponse(red)).state();
		double last_xpos = 0;
		while(true){			
			sleep(100);
			red.sendLine("getState");
			state = (new StateResponse(red)).state();
			Player player = state.team(Side.LEFT).player(0);
			double xpos = player.location().x;
			if (state.team(Side.LEFT).player(0).state() == Player.State.TCTF){
				break;
			}
			if(xpos <= last_xpos)
				break;
			last_xpos = xpos;
		}
		sleep(2000);
		red.sendLine("getState");
		state = (new StateResponse(red)).state();
		assertEquals(Player.State.DEFENDING, state.team(Side.LEFT).player(0).state());

	}
	
	public void testTCTFDecreasedByOpponent() throws IOException, NetworkException, ProtocolError, RoundOverException, GameOverException{
		Point playerPosition = new Point(20,125);
		Point player2Position = new Point(88,125);
		
		
		blue.sendLine("placePlayer 0 " + player2Position.toSTEAL());
		new CommandResponse(blue);

		red.sendLine("placePlayer 0 " + playerPosition.toSTEAL());
		new CommandResponse(red);
		
		red.sendLine("accelerate 0 0 2");
		new CommandResponse(red);
		sleep(1000);

		while(true){			
			sleep(100);
			red.sendLine("getState");
			State state = (new StateResponse(red)).state();
			Player player = state.team(Side.LEFT).player(0);
			Double speed = player.speed();
			if (state.team(Side.LEFT).player(0).location().x > 84){
				break;
			}
			if(speed == 0)
				break;
		}
		red.sendLine("getState");
		State state = (new StateResponse(red)).state();
		
		
		assertEquals(Player.State.DEFENDING, state.team(Side.LEFT).player(0).state());
	}
	
	
	
	
	
	public void testTCTFGoesToPrisionAfter7Sec() throws IOException, NetworkException, ProtocolError, RoundOverException, GameOverException{
		this.testTCTFIncreasedByOpponentRunningOut();
		sleep(8000);
		red.sendLine("getState");
		State state = (new StateResponse(red)).state();
		Player player = state.team(Side.LEFT).player(0);
		
		assertEquals(Player.State.PRISONER, player.state());
		
		
	}



}
